package com.hh.bidding.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSON;
import com.hh.bidding.domain.*;
import com.hh.bidding.service.*;
import com.hh.bidding.service.business.BidInvitationServiceBusiness;
import com.hh.bidding.service.business.BidRankingUtils;
import com.hh.bidding.service.business.IBidMailService;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.model.LoginUser;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.page.TableDataInfo;

/**
 * 招标公示/招标公告Controller
 *
 * @author ruoyi
 * &#064;date  2023-11-19
 */
@RestController
@RequestMapping("/notice")
public class BidNoticeController extends BaseController {
    @Resource
    private IBidNoticeService bidNoticeService;
    @Resource
    private IBidTenderQuotationService bidTenderQuotationService;
    @Resource
    private IBidTenderRulesService bidTenderRulesService;
    @Resource
    private IBidCandidateService bidCandidateService;
    @Resource
    private IBidTenderInvitationService bidTenderInvitationService;
    @Resource
    private IBidMailService bidMailService;
    @Resource
    private BidInvitationServiceBusiness bidInvitationServiceBusiness;

    private SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


    /**
     *
     */
    @GetMapping("/list")
    public TableDataInfo list(BidNotice bidNotice) {
        startPage();
        List<BidNotice> list = bidNoticeService.selectBidNoticeList(bidNotice);
        for (BidNotice b : list) {
            b.setResults(JSON.parseArray(b.getFjAnnex(), Result.class));
        }
        return getDataTable(list);
    }

    /**
     * 查询 招标公示/招标公告，今日竞标 列表
     * 1、招标公示/招标公告，主要转fjStatus = 5 已发布状态，以及uEndTime截止时间参数
     * 2、今日竞标，主要转fjStatus = 5 已发布状态，以及uKaiTime竞标时间参数
     */
    @GetMapping("/listFront")
    public TableDataInfo listFront(BidNotice bidNotice) {
        startPage();
        List<BidNotice> list = bidNoticeService.selectBidNoticeListByFront(bidNotice);
        for (BidNotice b : list) {
            b.setuMoney(0L);//项目金额，客户端不可见
            b.setResults(JSON.parseArray(b.getFjAnnex(), Result.class));
        }
        return getDataTable(list);
    }

    /**
     * 导出招标公告列表
     */
    @RequiresPermissions("system:notice:export")
    @Log(title = "招标公告", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, BidNotice bidNotice) {
        List<BidNotice> list = bidNoticeService.selectBidNoticeList(bidNotice);
        ExcelUtil<BidNotice> util = new ExcelUtil<BidNotice>(BidNotice.class);
        util.exportExcel(response, list, "招标公告数据");
    }

    /**
     * 获取招标公告详细信息
     */
    @RequiresPermissions("system:notice:query")
    @GetMapping(value = "/{uid}")
    public AjaxResult getInfo(@PathVariable("uid") Long uid) {
        return success(bidNoticeService.selectBidNoticeByUid(uid));
    }

    /**
     * 新增招标公告
     */
    @RequiresPermissions("system:notice:add")
    @Log(title = "招标公告", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody BidNotice bidNotice) {
        int rows = bidNoticeService.insertBidNotice(bidNotice);
        List<Long> list = bidNotice.getHids();
        if(list != null && list.size() > 0 && rows > 0){
            for(Long hid : list){
                BidTenderInvitation bidTenderInvitation = new BidTenderInvitation();
                bidTenderInvitation.setSid(bidNotice.getSid());
                bidTenderInvitation.setsCode(bidNotice.getsCode());
                bidTenderInvitation.setHid(hid);
                bidTenderInvitation.setUid(bidNotice.getUid());
                bidTenderInvitation.setCreateTime(new Date());
                try {
                    bidTenderInvitationService.insertBidTenderInvitation(bidTenderInvitation);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
        return toAjax(rows);
    }

    /**
     * 修改招标公告
     */
    @RequiresPermissions("system:notice:edit")
    @Log(title = "招标公告", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody BidNotice bidNotice) {
        List<Long> list = bidNotice.getHids();
        if(list != null && list.size() > 0){
            bidInvitationServiceBusiness.handlerInvitation(bidNotice.getUid(),bidNotice.getSid(),bidNotice.getsCode(),list);
        }
        //发邮件，只有在发布的时候才发邮件，添加和修改都不会发邮件，只是添加和修改邀请而已
        if(bidNotice.getFjStatus() == 5 && bidNotice.getRelease() == 1 && bidNotice.getSid() > 0){
            List<Long> tempList = new ArrayList<>();
            List<BsOperator> operatorsList = bidNoticeService.selectAllBsOperator();
            List<BidTenderInvitation> invitationList = bidTenderInvitationService.selectBidTenderInvitationListBySid(bidNotice.getSid());
            if(invitationList != null && invitationList.size() > 0){
                Map<Long,List<BidTenderInvitation>> map = invitationList.stream().collect(Collectors.groupingBy(BidTenderInvitation::getUid));
                if(map != null && map.size() > 0){
                    List<BidTenderInvitation> tempInvitationList = map.get(bidNotice.getUid());
                    for(BidTenderInvitation invitation : tempInvitationList){
                        tempList.add(invitation.getHid());
                    }
                }
            }
            //发布公告的时候发邮件
            Map<Long,BsOperator> map = new HashMap<>();
            if(operatorsList != null && operatorsList.size() > 0){
                for(BsOperator operator : operatorsList){
                    map.put(operator.getHid(),operator);
                }
            }
            for(Long hid : tempList){
                BsOperator operator = map.get(hid);
                if(operator != null){
                    String email = operator.getYwMailbox();
                    String title = bidNotice.getuTitle();
                    if(StringUtils.hasLength(title) && title.contains("公告")){
                        title = title.replace("公告","");
                    }
                    String resultTitle = title + "邀请";
                    boolean emailSuccess = false;
                    try{
                        if(StringUtils.hasLength(email) && StringUtils.hasLength(bidNotice.getFjRemark())){
                            bidMailService.sendHtmlMail(email,resultTitle,bidNotice.getFjRemark());
                            emailSuccess = true;
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }

        return toAjax(bidNoticeService.updateBidNotice(bidNotice));
    }



    /**
     * 删除招标公告
     */
    @RequiresPermissions("system:notice:remove")
    @Log(title = "招标公告", businessType = BusinessType.DELETE)
    @DeleteMapping("/{uids}")
    public AjaxResult remove(@PathVariable Long[] uids) {
        int rows = bidNoticeService.deleteBidNoticeByUids(uids);
        if(rows > 0){
            for(Long uid : uids){
                bidTenderInvitationService.deleteBidTenderInvitationByUId(uid);
            }
        }
        return toAjax(rows);
    }

    /**
     * 网站显示 中标结果
     * @return 返回中标结果
     */
    @PostMapping("/find")
    public AjaxResult findAllByEndTime() {
        List<BidNotice> list = bidNoticeService.findAllByEndTime();
        if(list != null && list.size() > 0){
            for (BidNotice b : list) {
                b.setuMoney(0L);//项目金额，客户端不可见
            }
        }
        return AjaxResult.success();
    }

    //判定是否已存在已发布状态
    @PostMapping("/findStatus")
    public AjaxResult findStatus(@Validated @RequestBody Long sid) {
        return AjaxResult.success(bidNoticeService.findStatus(sid));
    }

    /**
     * 删除已发布招标公告
     */
    @Log(title = "招标公告", businessType = BusinessType.DELETE)
    @DeleteMapping("/sc/{sid}")
    public AjaxResult remove123(@PathVariable Long sid) {
        BidNotice bidNotice = bidNoticeService.selectBidNoticeBySid(sid);
        int rows = bidNoticeService.deleteYfb(sid);
        if(rows > 0){
            //删除该公告邀请的供应商
            Long uid = bidNotice.getUid();
            bidTenderInvitationService.deleteBidTenderInvitationByUId(uid);
        }
        return toAjax(rows);
    }

    //两表联查 招标项目的招标公告信息
    @GetMapping(value = "/findTwoInfo/{uid}")
    public AjaxResult findTwoInfo(@PathVariable Long uid) {
        BidNotice bidNotice = bidNoticeService.findTwoInfo(uid);
        if(bidNotice != null){
            bidNotice.setuMoney(0L);//供应商不可见
            if(bidNotice.getBidTender() != null){
                bidNotice.getBidTender().setsBudget(0L);//供应商不可见
            }
        }
        return AjaxResult.success(bidNotice);
    }

    @GetMapping("/selMax")
    public AjaxResult selMax() {
        return AjaxResult.success(bidNoticeService.selMax());
    }


    /**
     * 根据sid修改公告公示时间
     * @return
     */
    @PutMapping("/updateStatus/{sid}")
    public AjaxResult updateStatus(@PathVariable Long sid) {
        return toAjax(bidNoticeService.updateStatus(sid));
    }

    /**
     * 结束竞价
     * @param sid
     * @return
     */
    @PutMapping("/updateUKaiEndTime/{sid}")
    public AjaxResult updateUKaiEndTime(@PathVariable Long sid) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if(loginUser != null && !"admin".equals(loginUser.getUsername())){
            return AjaxResult.error("非管理员无权限操作");
        }
        int rows = bidNoticeService.updateUKaiEndTime(sid);
        //
        List<BidTenderQuotation> list = bidTenderQuotationService.findAllListBySid(sid.intValue());
        if(list != null && list.size() > 0){
            Integer biddingMethodRadio = 1;
            BidTenderRules bidTenderRules = bidTenderRulesService.queryBySid(sid);
            if(bidTenderRules != null){
                biddingMethodRadio = bidTenderRules.getBiddingMethodRadio();//竞标方式：1按金额从小到大排名，2按降幅从大到小排名
            }
            Map<Integer,Integer> tempMap =new HashMap<>();
            List<BidCandidate> candidateList = new ArrayList<>();
            for(BidTenderQuotation tempQuotation : list){
                String sCode = tempQuotation.getsCode();
                Integer hid = tempQuotation.getHid();
                String hName = tempQuotation.gethName();
                Integer tempSorted = tempMap.get(hid);
                //排名
                BidRankingUtils.SupplierBidInfo ranking = BidRankingUtils.getSupplierRanking(Long.valueOf(hid), sCode, tempQuotation.getCreateTime(), biddingMethodRadio);
                if (ranking != null && tempSorted == null) {
                    Integer sorted = ranking.getRank();
                    boolean isWinner = ranking.getIsWinner();
                    //String hName = ranking.gethName();
                    BidCandidate bidCandidate = new BidCandidate();
                    bidCandidate.setSid(sid);//招标项目ID
                    bidCandidate.setHid(Long.valueOf(hid));//供应商ID
                    bidCandidate.sethName(hName);//供应商名称
                    bidCandidate.setzFinal(ranking.getBjTotal());//最终报价
                    long zFraction = 100L - Long.valueOf(sorted);
                    bidCandidate.setzFraction(zFraction);
                    bidCandidate.setzRanking(Long.valueOf(sorted));//排名
                    if(sorted == 1 && isWinner){
                        //中标供应商
                        bidCandidate.setzRecommend(0L);//推荐
                        bidCandidate.setzBidder(0L);//是否中标（是：0  否：1）
                    }else{
                        if(sorted <= 3){
                            bidCandidate.setzRecommend(0L);//推荐
                        }else{
                            bidCandidate.setzRecommend(1L);//不推荐
                        }
                        bidCandidate.setzBidder(1L);//是否中标（是：0  否：1）
                    }
                    bidCandidate.setzSendTime(DateUtils.getNowDate());
                    candidateList.add(bidCandidate);
                    tempMap.put(hid,sorted);
                }
            }
            if(candidateList.size() > 0){
                candidateList = candidateList.stream().filter(candidate -> candidate.getzRanking() != null).sorted(Comparator.comparing(BidCandidate::getzRanking)).collect(Collectors.toList());
                for (BidCandidate bidCandidate : candidateList){
                    BidCandidate oldBidCandidate = bidCandidateService.selectBidCandidateByHidAndSid(bidCandidate.getHid(),bidCandidate.getSid());
                    if(oldBidCandidate == null){
                        bidCandidateService.insertBidCandidate(bidCandidate);
                    }else{
                        oldBidCandidate.setzFinal(bidCandidate.getzFinal());
                        oldBidCandidate.setzFraction(bidCandidate.getzFraction());
                        oldBidCandidate.setzRecommend(bidCandidate.getzRecommend());
                        oldBidCandidate.setzRanking(bidCandidate.getzRanking());
                        oldBidCandidate.setzBidder(bidCandidate.getzBidder());
                        oldBidCandidate.setzSendTime(bidCandidate.getzSendTime());
                        oldBidCandidate.sethName(bidCandidate.gethName());
                        bidCandidateService.updateBidCandidate(oldBidCandidate);
                    }

                }
            }
        }

        return toAjax(rows);
    }

    /**
     * 延时竞价
     * @param bidNotice
     * @return
     */
    @PostMapping("/updateByUKaiEndTime")
    public synchronized AjaxResult updateByUKaiEndTime(@Validated @RequestBody BidNotice bidNotice) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if(loginUser != null && !"admin".equals(loginUser.getUsername())){
            return AjaxResult.error("非管理员无权限操作");
        }
        Long sid = bidNotice.getSid();
        int extendTime = 1;
        int extendCount = 999;
        int currentCount = 0;
        BidTenderRules bidTenderRules = bidTenderRulesService.queryBySid(sid);
        if(bidTenderRules != null){
            extendTime = bidTenderRules.getExtendTime();//延长时间，单位分钟
            extendCount = bidTenderRules.getExtendCount();//延长次数
            currentCount = bidTenderRules.getCurrentCount();//当前已经延长的次数
        }

        BidNotice oldBidNotice = bidNoticeService.selectBidNoticeBySid(sid);
        Date uKaiEndTime = oldBidNotice.getuKaiEndTime();
        Date newDate = addMinutesToDate(uKaiEndTime, extendTime);
        try {
            newDate = sf.parse(sf.format(newDate));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        bidNotice.setuKaiEndTime(newDate);
        int rows = 0;
        if(extendCount > currentCount){
            rows = bidNoticeService.updateBidNoticeBySid(bidNotice);
        }else{
            rows = -1;
        }
        if(rows > 0 && bidTenderRules != null){
            currentCount = currentCount + 1;
            bidTenderRules.setCurrentCount(currentCount);
            bidTenderRulesService.update(bidTenderRules);
        }
        if(rows > 0){
            return AjaxResult.success();
        }else if(rows == 0){
            return AjaxResult.error("延时失败");
        }else{
            return AjaxResult.error("延时失败，超过设定的延时次数，即将结束竞价");
        }
    }

    public Date addMinutesToDate(Date date, int minutes) {
        // 将Date转换为LocalDateTime
        LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        // 增加分钟数
        LocalDateTime newDateTime = localDateTime.plusMinutes(minutes).plusSeconds(5);//额外增加多5秒，留个前端刷新频率间隔
        // 转换回Date
        return Date.from(newDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

}
